﻿using System.Linq;
using cfg.card;
using cfg.character;
using cfg.pawn;
using kemocard.Scripts.Common;
using kemocard.Scripts.Module.Battle;
using kemocard.Scripts.Pawn;

namespace kemocard.Scripts.Card.Scripts;

public class C2 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.Target.Count <= 0) return;
        var isSpecial = (parent.Target[0].Attribute & (int)Attribute.FIRE) > 0;
        damage.Times = isSpecial ? 2 : 1;
    }
}

public class C3 : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = parent.CalculateRealTimeValue(parent.Value, 5f);
    }

    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Modifiers.Add(DamageModifier.NoGuard, 1);
    }
}

public class C4 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times = 3;
    }
}

public class C5 : BaseAttackCard;

public class C16 : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result += 5000 * parent.RealTimeChain;
    }
}

public class C18 : BaseAttackCard;

public class C20 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times = 2;
    }
}

public class C21 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage damage, BasePawn parent, float value)
    {
        if (Mod?.Teammates != null)
        {
            foreach (var teammate in Mod.Teammates)
            {
                var buff = StaticUtil.NewBuffOrNullById("21", parent);
                if (buff == null) break;
                buff.TempValue = value * 0.1f;
                buff.Description = $"2回合/物理防御提升{2000 + value * 0.1}";
                teammate.AddBuff(buff);
            }
        }

        damage.OnHit -= OnHit;
    }
}

public class C26 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.ChainNum < 2) return;
        if (damage.Modifiers.TryAdd(DamageModifier.DamageScale, 1.8f))
        {
            damage.Modifiers[DamageModifier.DamageScale] += 0.8f;
        }
    }
}

public class C27 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.ChainNum >= 4)
        {
            damage.Modifiers.Add(DamageModifier.NoGuard, 1);
        }
    }
}

public class C28 : BaseAttackCard;

public class C32 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (Mod?.Teammates != null && Mod.Teammates.Count(c => (c.Race & (int)Race.DRAGON) != 0) >= 2)
        {
            damage.OnHit += OnHit;
        }
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        HealStruct heal = new()
        {
            Value = (int)(arg3 * 0.3f),
            Role = arg1.User.Role,
            Attribute = arg1.Attribute,
            Target = arg1.Target,
            User = arg1.User,
        };
        Mod?.DoHeal(heal);
        arg1.OnHit -= OnHit;
    }
}

public class C33 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        var time = 1;
        if (Mod != null)
        {
            if (Mod.Teammates.Count(c => (c.Attribute & (int)Attribute.WATER) != 0) >= 2) time++;
            if (Mod.Teammates.Count(c => (c.Race & (int)Race.FELIDAE) != 0) >= 2) time++;
        }

        damage.Times = time;
    }
}

public class C41 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Tags.Remove(Tag.MATTACK);
        if (damage.ChainNum < 4) return;
        var extraDamage = new Damage
        {
            Attribute = damage.Attribute,
            ChainNum = damage.ChainNum,
            IsFinal = true,
            Role = damage.Role,
            Tags = damage.Tags,
            Target = damage.Target,
            User = damage.User,
            Times = 1,
            Value = damage.Value,
        };
        extraDamage.Tags.Remove(Tag.PATTACK);
        extraDamage.Tags.Add(Tag.MATTACK);
        AfterDoDamage += _ => Mod?.DoDamage(extraDamage);
    }
}

public class C42 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.Target is not { Count: > 0 }) return;
        if ((damage.Target[0].Attribute & (int)Attribute.WIND) > 0)
        {
            damage.Times += 1;
        }
    }
}

public class C43 : BaseAttackCard;

public class C47 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        var buff = StaticUtil.NewBuffOrNullById("47", arg2);
        if (buff != null)
        {
            foreach (var pawn in arg1.Target)
            {
                pawn.AddBuff(buff);
            }
        }

        arg1.OnHit -= OnHit;
    }
}

public class C48 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        var buff = StaticUtil.NewBuffOrNullById("48", arg2);
        if (buff != null)
        {
            foreach (var pawn in arg1.Target)
            {
                pawn.AddBuff(buff);
            }
        }

        arg1.OnHit -= OnHit;
    }
}

public class AcidWormSupport : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        AfterDoDamage += AfterDoDamageFunc;
    }

    private static void AfterDoDamageFunc(BaseBattleCard parent)
    {
        HealStruct heal = new()
        {
            Value = 7500 + parent.User.Heal,
            Role = Role.SUPPORT,
            Attribute = (int)Attribute.EARTH,
            Target = Mod?.Teammates.ToList<BasePawn>(),
            User = parent.User,
        };
        Mod?.DoHeal(heal);
    }
}

public class BatEarthAttack : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.ChainNum < 3) return;
        if (!damage.Modifiers.TryAdd(DamageModifier.DamageScale, 1.3f))
        {
            damage.Modifiers[DamageModifier.DamageScale] += 0.3f;
        }
    }
}

public class AcidWormAttacker : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        var buff = StaticUtil.NewBuffOrNullById("ACID_WORM_ATTACKER", arg2);
        if (buff != null)
        {
            foreach (var pawn in arg1.Target)
            {
                pawn.AddBuff(buff);
            }
        }

        arg1.OnHit -= OnHit;
    }
}

public class RoverTyphoonAttacker : BaseAttackCard;

public class SnStarAttacker : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        // damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0.7f);
        damage.Times = 2;
    }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0.7f);
    }
}

public class SnStarBlocker : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        // damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0f, 0.7f);
        damage.Times = 2;
    }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0f, 0.7f);
    }
}

public class FesZellerAttacker : BaseAttackCard
{
    // protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    // {
    //     damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0.5f, 0.5f);
    // }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0.5f, 0.5f);
    }
}

public class SnSethAttacker : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        // damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0.7f);
        damage.Times = 2;
    }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0.7f);
    }
}

public class C60 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        // damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0, 1.5f);
        damage.Times = 2;
    }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0, 1.5f);
    }
}

public class C65 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.Target is not { Count: > 0 } || (damage.Target[0].Attribute & (int)Attribute.WATER) <= 0) return;
        if (!damage.Modifiers.TryAdd(DamageModifier.DamageScale, 1.3f))
        {
            damage.Modifiers[DamageModifier.DamageScale] += 0.3f;
        }
    }
}

public class C68 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.ChainNum < 3) return;
        var d = new Damage()
        {
            Attribute = damage.Attribute,
            ChainNum = damage.ChainNum,
            Role = damage.Role,
            Tags = damage.Tags,
            Target = damage.Target,
            User = damage.User,
            Times = 1,
            Value = damage.Value,
        };
        d.Tags.Remove(Tag.PATTACK);
        d.Tags.Add(Tag.MATTACK);
        Mod?.DoDamage(d);
    }
}

public class C54 : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        // damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0f, 1f, 1f);
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        HealStruct heal = new()
        {
            Value = (int)(arg3 * 0.1f),
            Role = arg1.User.Role,
            Attribute = arg1.Attribute,
            Target = Mod?.Teammates.ToList<BasePawn>(),
            User = arg1.User,
        };
        Mod?.DoHeal(heal);
        arg1.OnHit -= OnHit;
    }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0f, 1f, 1f);
    }
}

public class SlimeEarthAttacker : BaseAttackCard;

public class SwanAttacker : BaseAttackCard;

public class SwanBlocker : BaseAttackCard;

public class LizEarthBlocker : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.TempUsedCard.Count >= 3)
        {
            damage.Times += 2;
        }
    }
}

public class SciSantosB : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        // damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 0f, 0.7f);
        damage.Times = 2;
    }

    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = (int)parent.CalculateRealTimeValue(parent.Value, 0f, 0.7f);
    }
}

public class SsRainsA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.TempUsedCard.Count >= 2)
        {
            damage.Times += 1;
        }

        if (damage.ChainNum >= 3)
        {
            damage.Times += 1;
        }
    }
}

public class SsRainsB : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.TempUsedCard.Count >= 2)
        {
            damage.Times += damage.ChainNum - 1;
        }
    }
}

public class FortisCarterA : BaseAttackCard;

public class KnightCollinA : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = parent.CalculateRealTimeValue(parent.Value, 0.7f);
    }

    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times = 2;
    }
}

public class FortisZellerA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.ChainNum < 3) return;
        if (!damage.Modifiers.TryAdd(DamageModifier.DamageScale, 1.3f))
        {
            damage.Modifiers[DamageModifier.DamageScale] += 0.3f;
        }
    }
}

public class FortisZellerB : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = parent.CalculateRealTimeValue(parent.Value, 0, 0.7f);
    }

    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times = 2;
    }
}

public class KnightForgeA : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        if (parent.User?.Power >= 30) result = parent.CalculateRealTimeValue(parent.Value, 2.5f);
    }

    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.Power >= 30)
        {
            damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, 2.5f);
        }
        else
        {
            damage.Value = (int)parent.CalculateRealTimeValue(parent.Value, parent.Tags);
        }

        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        if (arg1.User is BattleCharacter { Power: >= 30 } bc)
        {
            bc.Power -= 30;
        }
    }
}

public class KnightForgeG : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        var buff = StaticUtil.NewBuffOrNullById("KNIGHT_FORGE_G", arg1.User);
        if (buff == null || Mod?.Teammates == null) return;
        foreach (var pawn in Mod.Teammates)
        {
            buff.TempValue = 0.1f * arg3;
            pawn.AddBuff(buff);
        }
    }
}

public class KnightForgeS : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        result = parent.CalculateRealTimeValue(parent.Value, 0, .7f, .7f);
    }

    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times = 2;
    }
}

public class FlowerMerlinA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times = 2;
        if (!damage.Modifiers.TryAdd(DamageModifier.DamageScale, 1 + 0.15f * (damage.ChainNum - 1)))
        {
            damage.Modifiers[DamageModifier.DamageScale] += 0.15f * (damage.ChainNum - 1);
        }
    }
}

public class ValentineSsA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.Times += parent.User.Power / 20;
        parent.User.Power %= 20;
    }
}

public class ValentineSsS : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        damage.OnHit += OnHit;
    }

    private static void OnHit(Damage arg1, BasePawn arg2, float arg3)
    {
        var h = arg1.User is BaseCharacter bc ? bc.Heal : 0;
        HealStruct heal = new()
        {
            Value = 3000 + h,
            Role = arg1.User.Role,
            Attribute = arg1.Attribute,
            Target = Mod?.Teammates.ToList<BasePawn>(),
            User = arg1.User,
        };
        Mod?.DoHeal(heal);
        arg1.OnHit -= OnHit;
    }
}

public class MetalZcA : BaseAttackCard;

public class MetalZcB : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        var c = parent.User.TempUsedCard;
        if (c.Count(card => (card.Attribute & (int)Attribute.FIRE) > 1) >= 2)
        {
            damage.Times += 1;
        }

        if (c.Count(card => (card.Attribute & (int)Attribute.EARTH) > 1) >= 2)
        {
            damage.Times += 1;
        }
    }
}

public class SciRainsA : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        var c = parent.User.TempUsedCard.Count(card =>
            card.CardType is CardType.PATTACK or CardType.MATTACK);
        if (c >= 2)
        {
            result = parent.CalculateRealTimeValue(parent.Value, 0, 1);
        }
    }
}

public class OccultismTripleA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        var count = StaticUtil.CheckTeammateRaceCount([Race.UNKNOWN, Race.RABMOU, Race.FELIDAE]);
        if (count >= 2)
        {
            damage.Times += 1;
        }

        if (count >= 3)
        {
            damage.Tags.Add(Tag.DCRITICAL);
            damage.IsCritical = true;
        }
    }
}

public class OccultismTripleB : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        var count = StaticUtil.CheckTeammateRaceCount([Race.UNKNOWN, Race.RABMOU, Race.FELIDAE]);
        if (count > 1) damage.Times += count - 1;
    }
}

public class ChivalryFcA : BaseAttackCard;

public class WaiterCollinA : BaseAttackCard;

public class JamRzS : BaseAttackCard
{
    public JamRzS()
    {
        AfterDoDamage += AfterDoDamageFunc;
    }

    private void AfterDoDamageFunc(BaseBattleCard obj)
    {
        HealStruct heal = new()
        {
            Value = (int)obj.CalculateRealTimeValue(1, [Tag.HEAL, Tag.WATER, Tag.FIRE]),
            Role = Role.SUPPORT,
            Attribute = (int)(Attribute.WATER | Attribute.FIRE),
            Target = Mod?.Teammates.ToList<BasePawn>(),
            User = obj.User,
        };
        Mod?.DoHeal(heal);
        AfterDoDamage -= AfterDoDamageFunc;
    }
}

public class SwordRainsA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.TempUsedCard.Count(c => (c.Attribute & (int)Attribute.WATER) > 0) >= 2)
        {
            damage.Times += 1;
        }

        if (damage.ChainNum >= 4)
        {
            damage.Modifiers.TryAdd(DamageModifier.NoGuard, 1);
        }
    }
}

public class OnsenTyphoonA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.TempUsedCard.Count(c => (c.Attribute & (int)Attribute.WIND) > 0) >= 2)
        {
            damage.Times += 1;
        }
    }
}

public class OnsenSethA : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        if (parent.RealTimeChain >= 2)
        {
            result = parent.CalculateRealTimeValue(parent.Value, 5);
        }
    }

    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (damage.Target.All(pawn => (pawn.Attribute & (int)Attribute.EARTH) > 0))
        {
            damage.Times += 2;
        }
    }
}

public class OnsenSethG : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        if (parent.RealTimeChain >= 4)
        {
            result = parent.CalculateRealTimeValue(parent.Value * 10, parent.Tags);
        }
    }
}

public class OnsenStarA : BaseAttackCard;

public class AllegoryTpB : BaseAttackCard;

public class AllegorySethA : BaseAttackCard
{
    protected override void CustomizeDamage(ref Damage damage, BaseBattleCard parent)
    {
        if (parent.User.Deck.Count(c => (c.Attribute & (int)Attribute.WIND) > 0) >= 5)
        {
            damage.Times += 1;
        }
    }
}

public class HalloweenEllisA : BaseAttackCard
{
    public override void UpdateRealTimeValue(BaseBattleCard parent, ref float result)
    {
        if (parent.RealTimeChain >= 3)
        {
            result = parent.CalculateRealTimeValue(parent.Value, 2.5f);
        }
    }
}